<?php
/**
 * User:于小涛
 * Date:2020/2/16
 * Time:16:56
 */
namespace app\admin\business\rbac;

use app\admin\model\rbac\Admin;
use app\admin\model\rbac\Auth as AuthModel;
use think\facade\Db;

class Auth{
    private $obj_auth_model=null;
    public function __construct()
    {
        $this->obj_auth_model = new AuthModel();
    }

    /**
     * 根据token获取管理员信息
     * User:于小涛
     * Date:2020/2/16
     * Time:17:15
     * @param string $str_token token
     * @return array $arr_admin_info
     */
    public function getAdminInfoByToken($str_token){
        $str_cache_key='admin:'.$str_token;
        $arr_admin_info= cache($str_cache_key);
        if($arr_admin_info){
            trace("从缓存获取管理员信息成功",'info');
            return $arr_admin_info;
        }
        $arr_admin_info = Admin::field('id,account,name,type,last_login_time,last_login_ip,token')
            ->where('token', $str_token)
            ->findOrEmpty()
            ->toArray();
        //缓存信息
        if($arr_admin_info){
            $bool_re=cache($str_cache_key,$arr_admin_info,config("cache.token_expire"),config('cache.admin_session_tag'));
            if(!$bool_re){
                trace("缓存登录信息失败",'error');
            }else{
                trace("缓存登录信息成功",'info');
            }
        }
        return $arr_admin_info;
    }

    public function login($str_account,$str_pwd){
        $obj_admin_model = new Admin();
        $arr_admin_info = $obj_admin_model->getAdminInfoByAccountPwd($str_account,$str_pwd);
        //如果不为空，更新最后登录时间和登陆ip
        if(!empty($arr_admin_info)){
            $obj_admin_model->updateLoginData($arr_admin_info['id']);
        }
        return $arr_admin_info;
    }

    /**
     * 根据管理员iD获取权限ids
     * User:于小涛
     * Date:2020/2/17
     * Time:11:20
     * @param int $int_admin_id 管理员id
     * @return array $arr_ids
     */
    public function getAuthIdsByAdminId($int_admin_id){
        $str_sql="select ra.* from rbac_admin as a,rbac_admin_role as ar,rbac_role_auth as ra where a.id=ar.admin_id and ar.role_id=ra.role_id AND a.id=?";
        $arr_data=Db::query($str_sql,[$int_admin_id]);
        $arr_ids=[];
        foreach($arr_data as $arr_item){
            $arr_ids[]=$arr_item['auth_id'];
        }
        return $arr_ids;
    }

    /**
     * 获取权限菜单
     * User:于小涛
     * Date:2020/2/18
     * Time:11:54
     */
    public function getAuthListStruct(){
        $arr_auth=array();
        $arr_admin_info=session('admin');
        switch ($arr_admin_info['type']){
            case 0:
                $arr_auth=null;
                break;
            case 1:
                $arr_auth=array();
                break;
            case 2:
                $arr_auth=$_SESSION['auth']['auth'];
                break;
        }
        $arr_list_auth_mul=array();
        $arr_list_auth_one=array();
        $this->getAllMenuTree(0, $arr_auth,$arr_list_auth_mul,array(),false);
        $this->_proAuthToOne($arr_list_auth_mul,$arr_list_auth_one);
        return $arr_list_auth_one;
    }
    /**
     * 获取所有权限树形结构
     * User:于小涛
     * Date:2020/2/18
     * Time:11:54
     * @param int $int_pid 权限的pid
     * @param array $arr_auth_ids 查询哪些指定id的权限，如果是超级管理员则为0，如果是系统管理员则为1
     * @param array $arr_auth 查询结果
     * @param array $arr_exclude_auth_id 需要排除的权限
     * @param bool $bool_only_menu 是否只获取菜单，如果是则不会获取页面上的操作权限
     * @param array $arr_checked_auth_ids 当前角色已经绑定的权限
     * @return null
     */
    public function getAllMenuTree($int_pid=0,$arr_auth_ids=array(),&$arr_auth=array(),$arr_exclude_auth_id=array(),$bool_only_menu=true,$arr_checked_auth_ids=array()){
        //首先获取顶级的全部由权限的菜单
        $arr_where=array(
            array('pid','=',$int_pid),
            array('is_del','=',1),
        );
        //如果不为空，标识为普通管理员，则获取当前权限内所有开启的权限
        if(is_array($arr_auth_ids)){
            if(empty($arr_auth_ids)){
                $arr_auth=array();
                return ;
            }
            $arr_where[]=array(
                'id','in',$arr_auth_ids,
            );
            $arr_where[]=array(
                'is_lock','=',1,
            );
        }
        $arr_auth=$this->obj_auth_model->getList($arr_where,1,1000000,array('order_num'=>'desc'));
        if(empty($arr_auth)){
            return '';
        }
        foreach($arr_auth as $int_id=>&$arr_item){
            //如果需要排除
            if(in_array($arr_item['id'],$arr_exclude_auth_id)){
                unset($arr_auth[$int_id]);
                continue;
            }
            if(in_array($arr_item['id'],$arr_checked_auth_ids)){
                $arr_item['checked']=true;
            }
            $arr_item['child']=array();
            //url地址不为空，并且不是3级权限的不要，因为如果是一级或者二级权限有url地址则是不需要添加子集菜单的，然后4级菜单本身就不能够添加子集菜单
            if(!empty($arr_item['url'])&&$arr_item['level']>3&&$bool_only_menu){
                unset($arr_auth[$int_id]);
                continue;
            }
            //为空或者不为空并且要求获取页面操作权限才继续获取子级
            if(empty($arr_item['url'])){
                $this->getAllMenuTree($arr_item['id'],$arr_auth_ids,$arr_item['child'],$arr_exclude_auth_id,$bool_only_menu,$arr_checked_auth_ids);
            }elseif(!$bool_only_menu){
                $this->getAllMenuTree($arr_item['id'],$arr_auth_ids,$arr_item['child'],$arr_exclude_auth_id,$bool_only_menu,$arr_checked_auth_ids);
            }
            if(empty($arr_item['child'])){
                unset($arr_item['child']);
            }
        }
        return '';
    }

    /**
     * 将多维的权限处理为一维
     * User:于小涛
     * Date:2020/2/18
     * Time:12:54
     * @param array $arr_list_data 权限多维结构数组
     * @param array $arr_return_auth 最终返回的一级权限结构
     * @param int $int_deep 当前权限第几级，默认第一级
     * @return null
     */
    private function _proAuthToOne($arr_list_data=array(),&$arr_return_auth=array(),$int_deep=1){
        if(empty($arr_list_data)){
            return '';
        }
        foreach($arr_list_data as $arr_auth_item){
            $arr_tmp=$arr_auth_item;
            if(!empty($arr_auth_item['icon'])){
                $arr_tmp['icon']="<i class='layui-icon {$arr_auth_item['icon']}'></i>";
            }
            if($int_deep==1){
                $arr_tmp['name']="|--".$arr_tmp['name'];
            }else if ($int_deep>1){
                $arr_tmp['name']="|--".str_pad("",($int_deep-1)*3,'-').$arr_tmp['name'];
            }
            unset($arr_tmp['child']);
            $arr_return_auth[]=$arr_tmp;
            if(array_key_exists('child',$arr_auth_item)&&!empty($arr_auth_item['child'])){
                $this->_proAuthToOne($arr_auth_item['child'],$arr_return_auth,$int_deep+1);
            }
        }
    }


    /**
     * 获取权限select的option带html的字符串
     * User:于小涛
     * Date:2020/2/18
     * Time:13:54
     * @param int $int_pid 权限的pid
     * @param array $arr_auth_ids 查询哪些指定id的权限，如果是超级管理员则为null，如果是系统管理员则为空数组
     * @param int $int_selected_id 当前的id，传递了则会自动选中对应的option
     * @param array $arr_exclude_auth_id 需要排除的id
     * @return string $str_re;
     */
    public function getMenuHtmlOption($int_pid=0,$arr_auth_ids=array(),$int_selected_id=null,$arr_exclude_auth_id=array()){
        $arr_auth=array();
        $this->getAllMenuTree($int_pid,$arr_auth_ids,$arr_auth,$arr_exclude_auth_id);
        $str_option_html='';
        $this->_getMenuHtmlOption($arr_auth,$str_option_html,1,$int_selected_id);
        return $str_option_html;
    }

    private function _getMenuHtmlOption($arr_auth=array(),&$str_option_html='',$int_deep=1,$int_selected_id=''){
        if(is_array($arr_auth)){
            foreach($arr_auth as $arr_item){
                if($int_deep==1){
                    $arr_item['name']="|--".$arr_item['name'];
                }else if ($int_deep>1){
                    $arr_item['name']="|--".str_pad("",($int_deep-1)*3,'-').$arr_item['name'];
                }
                $str_selected='';
                if($arr_item['id']==$int_selected_id){
                    $str_selected="selected";
                }
                $str_option_html.="<option value='{$arr_item['id']}' {$str_selected}>{$arr_item['name']}</option>";
                if(!empty($arr_item['child'])){
                    $this->_getMenuHtmlOption($arr_item['child'],$str_option_html,$int_deep+1,$int_selected_id);
                }
            }
        }
    }

    /**
     * 通过pid获取当前等级level
     * User:于小涛
     * Date:2020/2/18
     * Time:13:04
     * @param $int_pid pid
     * @return int|mixed
     */
    public function getLevelByPid($int_pid){
        $arr_info=$this->obj_auth_model->findOrEmpty($int_pid);
        if(empty($arr_info)){
            return 1;
        }else{
            return $arr_info['level']+1;
        }
    }

    public function getAuthTree($int_role_id=0){
        $arr_current_auth_ids=array();
        if($int_role_id){
            $str_sql="select * from rbac_role_auth where role_id=".$int_role_id;
            $arr_role_auth=$this->obj_auth_model->query($str_sql);
            foreach($arr_role_auth as $arr_item){
                $arr_current_auth_ids[]=$arr_item['auth_id'];
            }
        }
        $arr_list_data=array();
        $arr_admin_info=session('admin');
        $this->getAllMenuTree(0,$arr_admin_info['auth_ids'],$arr_list_data,array(),false,$arr_current_auth_ids);
        recursionReplaceArrayKey($arr_list_data,array('id'=>'value','child'=>'list'));
        return $arr_list_data;
    }

    /**
     * 通过角色监测权限
     * User:于小涛
     * Date:2020/2/24
     * Time:15:19
     * @param $str_auth_url
     * @param bool $bool_auto_system_admin 是否自动判断系统管理员
     * @return bool
     */
    public static function checkAuthByRoute($str_auth_url,$bool_auto_system_admin=true){
        $arr_admin_info=session('admin');
        if($bool_auto_system_admin&&($arr_admin_info['type']==0||$arr_admin_info['type']==1)){
            return true;
        }
        if(in_array($str_auth_url,$arr_admin_info['auth_urls'])){
            return true;
        }
        return false;
    }

    /**
     * 通过管理员id获取该管理员的权限路由
     * User:于小涛
     * Date:2020/2/24
     * Time:17:19
     */
    public function getAuthUrls($int_admin_id){
        $str_sql="select auth.url from rbac_admin as admin left join rbac_admin_role as admin_role on admin_role.admin_id=admin.id left join rbac_role_auth as role_auth on role_auth.role_id=admin_role.role_id left join rbac_auth as auth on auth.id=role_auth.auth_id where admin.id={$int_admin_id}";
        $arr_data=$this->obj_auth_model->query($str_sql);
        if(empty($arr_data)){
            return [];
        }
        $arr_urls=[];
        foreach($arr_data as $arr_item){
            $arr_urls[]=$arr_item['url'];
        }
        return $arr_urls;
    }

}